#include "Config.h"
#include "Common/Stream.h"
#include "ServerClient.h"
#include "ServerClientManager.h"
#include "DBCache/DBDataExecHelper.h"
#include "DB/DBExecutor.h"
#include "Server.h"

ServerClientManager::ServerClientManager()
{

}

ServerClientManager::~ServerClientManager()
{

}

bool ServerClientManager::load()
{
	std::unique_ptr<DBExecutor> execu(gPlatDBConnectionMgr->GetExecutor());
	if (execu.get() == NULL || !execu->isConnected()) return false;
	DBServerData dsd;
	if(execu->Prepare("SELECT `id`, `name`, `type`, `innter_ip`, `outter_ip`, `port`, `roomCount`, `onlineCount` FROM `servers`", dsd) != DB_OK)
		return false;
	char buffer[1024] = { 0 };
	while(execu->Next() == DB_OK)
	{
		if ( dsd._type != 2 )
			continue;
		ServerClient * sc = new(std::nothrow) ServerClient();
		ServerData sd;
		sd._id = dsd._id;
		sd._name = dsd._name;
		sd._type = dsd._type;
		sd._innterIp = dsd._innterIp;
		sd._outerIp = dsd._outerIp;
		sd._port = dsd._port;
		sd._roomCount = dsd._roomCount;
		sd._onlineCount = dsd._onlineCount;
		sc->setServerData( sd );
		addServerClient( sc );
	}
	return true;
}

void ServerClientManager::update( UInt32 now )
{
	//ServerClient * sc = nullptr;
	//for ( auto itr = _serverClients.begin(); itr != _serverClients.end(); ++ itr )
	//{
	//	sc = itr->second;
	//	sc->saveServerData();
	//}
}

void ServerClientManager::addServerClient( ServerClient * sc )
{
	_serverClients.insert( std::make_pair( sc->getId(), sc ) );
}

void ServerClientManager::broadcast(Stream& st)
{
	ServerClient * sc = nullptr;
	for (auto itr = _serverClients.begin(); itr != _serverClients.end(); ++itr)
	{
		sc = itr->second;
		sc->send(st);
	}
}

void ServerClientManager::getOnlineCount( UInt32& playerCount, UInt32& roomCount )
{
	playerCount = 0;
	roomCount = 0;
	ServerClient * sc = nullptr;
	for (auto itr = _serverClients.begin(); itr != _serverClients.end(); ++itr)
	{
		sc = itr->second;
		playerCount += sc->getOnlineCount();
		roomCount += sc->getRoomCount();
	}
}


ServerClient * ServerClientManager::getServerClient( UInt32 sid )
{
	auto found = _serverClients.find( sid );
	return found == _serverClients.end() ? nullptr : found->second;
}

ServerClient * ServerClientManager::selectIdleServerClient()
{
	UInt32 minRoomCount = static_cast<UInt32>(-1);
	ServerClient * sc = nullptr;
	ServerClient * selectSc = nullptr;
	for ( auto itr = _serverClients.begin(); itr != _serverClients.end(); ++ itr )
	{
		sc = itr->second;
		if (sc->isConned() && sc->getRoomCount() < minRoomCount)
		{
			selectSc = sc;
			minRoomCount = sc->getRoomCount();
		}
	}
	return selectSc;
}